﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SpriteExtractor.View
{
    /// <summary>
    /// Interaction logic for Sprite.xaml
    /// </summary>
    public partial class Sprite : Canvas
    {

        public Sprite()
        {
            InitializeComponent();

            {
                var widthBinding = new Binding() { Path = new PropertyPath("Width"), Mode = BindingMode.TwoWay};
                this.SetBinding(WidthOriginalProperty, widthBinding);
            }

            {
                var heightBinding = new Binding() { Path = new PropertyPath("Height"), Mode = BindingMode.TwoWay};
                this.SetBinding(HeightOriginalProperty, heightBinding);
            }

        }

        #region Handlers of events from a sprite rect

        private void SpriteRect_MouseDown(object sender, MouseButtonEventArgs e)
        {
            var spriteViewModel = this.DataContext as ViewModel.SpriteViewModel;
            diffForRect = e.GetPosition(this) - spriteViewModel.Rect.TopLeft;

            spriteRect.CaptureMouse();
        }

        private void SpriteRect_MouseUp(object sender, MouseButtonEventArgs e)
        {
            spriteRect.ReleaseMouseCapture();
        }

        Vector diffForRect;
        private void SpriteRect_MouseMove(object sender, MouseEventArgs e)
        {
            var spriteViewModel = this.DataContext as ViewModel.SpriteViewModel;
            if (e.LeftButton == MouseButtonState.Pressed && spriteViewModel != null)
            {
                Point mousePos = e.GetPosition(this);
                spriteViewModel.Rect = new Rect(mousePos - diffForRect, spriteViewModel.Rect.Size);
            }
        }

        #endregion

        #region Handlers of events from an anchor point

        private void Anchor_MouseDown(object sender, MouseButtonEventArgs e)
        {
            var spriteViewModel = this.DataContext as ViewModel.SpriteViewModel;
            diffForAnchor = e.GetPosition(this) - spriteViewModel.Anchor;

            spriteAnchorEll.CaptureMouse();
        }

        private void Anchor_MouseUp(object sender, MouseButtonEventArgs e)
        {
            spriteAnchorEll.ReleaseMouseCapture();
        }

        Vector diffForAnchor;
        private void Anchor_MouseMove(object sender, MouseEventArgs e)
        {
            var spriteViewModel = this.DataContext as ViewModel.SpriteViewModel;
            if (e.LeftButton == MouseButtonState.Pressed && spriteViewModel != null)
            {
                Point mousePos = e.GetPosition(this);
                var anchorPos = (Point)(mousePos - diffForAnchor);
                if (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt))
                {
                    double stepHor = spriteViewModel.Rect.Size.Width * 0.05;
                    double stepVert = spriteViewModel.Rect.Size.Height * 0.05;
                    spriteViewModel.Anchor = new Point( 
                        Math.Round( anchorPos.X / stepHor, 0) * stepHor, 
                        Math.Round( anchorPos.Y / stepVert, 0) * stepVert);
                }
                else
                {
                    spriteViewModel.Anchor = anchorPos;
                }
            }
        }

        #endregion

        #region Event hadlers of TextBlock

        private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                textBlock.Visibility = Visibility.Collapsed;
                textBox.Visibility = Visibility.Visible;
                textBox.SelectAll();
            }
        }
        
        private void textBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter || e.Key == Key.Escape)
            {
                textBlock.Visibility = Visibility.Visible;
                textBox.Visibility = Visibility.Collapsed;
            }
        }
        #endregion

        #region Event hadlers of SizeRect

        private void SizeRect_MouseDown(object sender, MouseEventArgs e)
        {
            oldPosForSizeRect = e.GetPosition(this);
            oldSizeForSizeRect = new Size(WidthControl, HeightControl);
            sizeRect.CaptureMouse();
        }

        private void SizeRect_MouseUp(object sender, MouseEventArgs e)
        {
            sizeRect.ReleaseMouseCapture();
        }

        Point oldPosForSizeRect;
        Size oldSizeForSizeRect;
        private void SizeRect_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Point newPos = e.GetPosition(this);
                Vector diff  = newPos - oldPosForSizeRect;
                
                double w = oldSizeForSizeRect.Width + diff.X;
                double h = oldSizeForSizeRect.Height + diff.Y;
                if (w > 3 && h > 3)
                {
                    WidthControl = w;
                    HeightControl = h;
                }
            }
        }

        #endregion

        #region Convertion from/to the width of the spriteRect control and the width of the model

        public static readonly DependencyProperty WidthControlProperty =
            DependencyProperty.Register("WidthControl", typeof(double),
            typeof(Sprite), new FrameworkPropertyMetadata(0.0, (PropertyChangedCallback) 
                (
                    (depObj, e)=> depObj.SetValue(WidthOriginalProperty, (double)e.NewValue - 1) 
                )
                ));
        public double WidthControl
        {
            get { return (double)GetValue(WidthControlProperty); }
            set { SetValue(WidthControlProperty, value); }
        }

        
        public static readonly DependencyProperty WidthOriginalProperty =
            DependencyProperty.Register("WidthOriginal", typeof(double),
            typeof(Sprite), new FrameworkPropertyMetadata(0.0, (PropertyChangedCallback)
                (
                    (depObj, e) => depObj.SetValue(WidthControlProperty, (double)e.NewValue + 1)
                )
                ));
        public double WidthOriginal
        {
            get { return (double)GetValue(WidthOriginalProperty); }
            set { SetValue(WidthOriginalProperty, value); }
        }

        #endregion

        #region Convertion from/to the height of the spriteRect control and the height of the model


        public static readonly DependencyProperty HeightControlProperty =
            DependencyProperty.Register("HeightControl", typeof(double),
            typeof(Sprite), new FrameworkPropertyMetadata(0.0, (PropertyChangedCallback)
                (
                    (depObj, e) => depObj.SetValue(HeightOriginalProperty, (double)e.NewValue - 1)
                )
                ));
        public double HeightControl
        {
            get { return (double)GetValue(HeightControlProperty); }
            set { SetValue(HeightControlProperty, value); }
        }

        public static readonly DependencyProperty HeightOriginalProperty =
            DependencyProperty.Register("HeightOriginal", typeof(double),
            typeof(Sprite), new FrameworkPropertyMetadata(0.0, (PropertyChangedCallback)
                (
                    (depObj, e) => depObj.SetValue(HeightControlProperty, (double)e.NewValue + 1)
                )
                ));
        public double HeightOriginal
        {
            get { return (double)GetValue(HeightOriginalProperty); }
            set { SetValue(HeightOriginalProperty, value); }
        }

        #endregion



    }

    

}
